package com.khstudio.videocapture.gl;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.opengl.GLUtils;

public final class SquareClipGL2D {
    public static final int CLIP_LINE_CLICK_NONE   = 0x0000;
    public static final int CLIP_LINE_CLICK_LEFT   = 0x0001;
    public static final int CLIP_LINE_CLICK_RIGHT  = 0x0002;
    public static final int CLIP_LINE_CLICK_TOP    = 0x0004;
    public static final int CLIP_LINE_CLICK_BOTTOM = 0x0008;
    public static final int CLIP_LINE_CLICK_ALL    = CLIP_LINE_CLICK_LEFT | CLIP_LINE_CLICK_RIGHT | CLIP_LINE_CLICK_TOP | CLIP_LINE_CLICK_BOTTOM;

    private int mViewHeight;

    private FloatBuffer mVertexBuffer;
    private FloatBuffer mTextureBuffer;
    private ByteBuffer  mIndexBuffer;
    private int mIndiceslength;

//    private FloatBuffer mVertexBufferLn;
//    private FloatBuffer mTextureBufferLn;
//    private ByteBuffer  mIndexBufferLn;
//    private int mIndiceslengthLn;

    private FloatBuffer mVertexBufferLnLeft;
    private FloatBuffer mTextureBufferLnLeft;
    private ByteBuffer  mIndexBufferLnLeft;
    private int mIndiceslengthLnLeft;

    private FloatBuffer mVertexBufferLnRight;
    private FloatBuffer mTextureBufferLnRight;
    private ByteBuffer  mIndexBufferLnRight;
    private int mIndiceslengthLnRight;

    private FloatBuffer mVertexBufferLnBottom;
    private FloatBuffer mTextureBufferLnBottom;
    private ByteBuffer  mIndexBufferLnBottom;
    private int mIndiceslengthLnBottom;

    private FloatBuffer mVertexBufferLnTop;
    private FloatBuffer mTextureBufferLnTop;
    private ByteBuffer  mIndexBufferLnTop;
    private int mIndiceslengthLnTop;

    private int[] mTextures = new int[3];

    private int mHeight;
    private int mWidth;

    private int mLeft;
    private int mRight;
    private int mBottom;
    private int mTop;

    private int mLeftLn;
    private int mRightLn;
    private int mBottomLn;
    private int mTopLn;

    private int mWidthLn;
    private int mWidthLnCur;

    private float mTranslateX;
    private float mTranslateY;

    private float mScaleX;
    private float mScaleY;

    private int mColor;
    private int mColorLn;
    private int mColorLnAct;

    private int mClickBufferSize;
    private int mClickDrawLineFlag;

    private SquareClipGL2D() {
        mViewHeight = 0;

        mHeight = 0;;
        mWidth = 0;

        mLeft = 0;
        mTop = 0;
        mRight = 0;
        mBottom = 0;

        mLeftLn = 0;
        mRightLn = 0;
        mBottomLn = 0;
        mTopLn = 0;

        mTranslateX = 0;
        mTranslateY = 0;

        mScaleX = 1f;
        mScaleY = 1f;

        mColor = 0x60303030;
        mColorLn = 0xd0f0f0f0;
        mColorLnAct = 0xd000d0d0;

        mWidthLn = 2;
        mWidthLnCur = 0;

        mClickBufferSize = 20;
        mClickDrawLineFlag = CLIP_LINE_CLICK_NONE;
    }

    public static SquareClipGL2D create(GL10 gl) {
        SquareClipGL2D draw2D = new SquareClipGL2D();

        draw2D.loadTexture(gl);
        return draw2D;
    }

    public void draw(GL10 gl) {
        gl.glMatrixMode(GL10.GL_MODELVIEW);
        gl.glLoadIdentity();
        gl.glPushMatrix();

        gl.glScalef(mScaleX, mScaleY, 1f);
        gl.glTranslatef(mTranslateX, mTranslateY, -1f);

        gl.glMatrixMode(GL10.GL_TEXTURE);
        gl.glLoadIdentity();

        // Draw
        gl.glFrontFace(GL10.GL_CCW);
        gl.glEnable(GL10.GL_CULL_FACE);
        gl.glCullFace(GL10.GL_BACK);

        gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        // External Square
        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[0]);


        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mVertexBuffer);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBuffer);

        gl.glDrawElements(GL10.GL_TRIANGLES, mIndiceslength, GL10.GL_UNSIGNED_BYTE, mIndexBuffer);

        // Line Square
//        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[2]);
//
//
//        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mVertexBufferLn);
//        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBufferLn);
//
//        gl.glDrawElements(GL10.GL_TRIANGLES, mIndiceslengthLn, GL10.GL_UNSIGNED_BYTE, mIndexBufferLn);

        // In Line Left
        if((mClickDrawLineFlag & CLIP_LINE_CLICK_LEFT) == CLIP_LINE_CLICK_LEFT) gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[2]);
        else                                                                    gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[1]);

        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mVertexBufferLnLeft);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBufferLnLeft);

        gl.glDrawElements(GL10.GL_TRIANGLES, mIndiceslengthLnLeft, GL10.GL_UNSIGNED_BYTE, mIndexBufferLnLeft);

        // In Line Bottom
        if((mClickDrawLineFlag & CLIP_LINE_CLICK_BOTTOM) == CLIP_LINE_CLICK_BOTTOM) gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[2]);
        else                                                                        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[1]);

        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mVertexBufferLnBottom);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBufferLnBottom);

        gl.glDrawElements(GL10.GL_TRIANGLES, mIndiceslengthLnBottom, GL10.GL_UNSIGNED_BYTE, mIndexBufferLnBottom);

        // In Line Right
        if((mClickDrawLineFlag & CLIP_LINE_CLICK_RIGHT) == CLIP_LINE_CLICK_RIGHT) gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[2]);
        else                                                                      gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[1]);

        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mVertexBufferLnRight);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBufferLnRight);

        gl.glDrawElements(GL10.GL_TRIANGLES, mIndiceslengthLnRight, GL10.GL_UNSIGNED_BYTE, mIndexBufferLnRight);

        // In Line Top
        if((mClickDrawLineFlag & CLIP_LINE_CLICK_TOP) == CLIP_LINE_CLICK_TOP) gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[2]);
        else                                                                  gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[1]);

        gl.glVertexPointer(2, GL10.GL_FLOAT, 0, mVertexBufferLnTop);
        gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, mTextureBufferLnTop);

        gl.glDrawElements(GL10.GL_TRIANGLES, mIndiceslengthLnTop, GL10.GL_UNSIGNED_BYTE, mIndexBufferLnTop);

        gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
        gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);

        gl.glDisable(GL10.GL_CULL_FACE);
        // Draw

        gl.glPopMatrix();
        gl.glLoadIdentity();
    }

    public void move(int x, int y) {
        mTranslateX = x;
        mTranslateY = y;
    }

    public void move(float x, float y) {
        mTranslateX = x;
        mTranslateY = y;
    }

    public void scale(float x, float y) {
        mScaleX = x;
        mScaleY = y;

        int widthLnCur = (mScaleX < 1 ? (int) Math.ceil(mWidthLn / mScaleX) : mWidthLn);
        if(mWidthLnCur != widthLnCur) {
            mWidthLnCur = widthLnCur;
            refreshVertices();
        }
    }

    public boolean checkIncludePosition(int x, int y) {
        if((getLeft() <= x) && (getRight() >= x) && (getTop() >= y) && (getBottom() <= y)) {
            return true;
        }
        return false;
    }

    public int checkInsideLineFromView(float x, float y) {
        float glX = (float) x / mScaleX - mTranslateX;
        float glY = ((mViewHeight - (float) y) / mScaleY) - mTranslateY;
        float clickbuffersize = mClickBufferSize / mScaleX;

        float leftLine_L = mLeftLn - clickbuffersize;
        float leftLine_R = mLeftLn + clickbuffersize;

        float rightLine_L = mRightLn - clickbuffersize;
        float rightLine_R = mRightLn + clickbuffersize;

        float bottomLine_B = mBottomLn - clickbuffersize;
        float bottomLine_T = mBottomLn + clickbuffersize;

        float topLine_B = mTopLn - clickbuffersize;
        float topLine_T = mTopLn + clickbuffersize;

        int clickFlag = CLIP_LINE_CLICK_NONE;

//        log.e("checkInsideLine x = %d, y = %d",x,y);
//        log.e("checkInsideLine mTranslateX = %f, mTranslateY = %f",mTranslateX,mTranslateY);
//        log.e("checkInsideLine mScaleX = %f, mScaleY = %f",mScaleX,mScaleY);
//        log.e("checkInsideLine glX = %f, glY = %f",glX,glY);
//        log.e("checkInsideLine l = %d, r = %d b = %d t = %d",mLeftLn,mRightLn,mBottomLn,mTopLn);

        if(glX >= leftLine_L && glX <= rightLine_R) {
            if(glX <= leftLine_R)           clickFlag = CLIP_LINE_CLICK_LEFT;
            else if(glX >= rightLine_L)     clickFlag = CLIP_LINE_CLICK_RIGHT;
            else                            clickFlag = CLIP_LINE_CLICK_LEFT | CLIP_LINE_CLICK_RIGHT;

//            log.e("CLIP_LINE_CLICK_LEFT left 1 = %f, left 2 = %f glx = %f",mLeftLn - clickbuffersize,mLeftLn + clickbuffersize,glX);
        }
        if(glY >= bottomLine_B && glY <= topLine_T) {
            if((clickFlag & (CLIP_LINE_CLICK_LEFT | CLIP_LINE_CLICK_RIGHT)) == (CLIP_LINE_CLICK_LEFT | CLIP_LINE_CLICK_RIGHT)) {
                if(glY <= bottomLine_T)     clickFlag = CLIP_LINE_CLICK_BOTTOM;
                else if(glY >= topLine_B)   clickFlag = CLIP_LINE_CLICK_TOP;
                else                        clickFlag |= CLIP_LINE_CLICK_BOTTOM | CLIP_LINE_CLICK_TOP;
            } else if((clickFlag & CLIP_LINE_CLICK_LEFT | CLIP_LINE_CLICK_RIGHT) != 0) {
                if(glY <= bottomLine_T)     clickFlag |= CLIP_LINE_CLICK_BOTTOM;
                else if(glY >= topLine_B)   clickFlag |= CLIP_LINE_CLICK_TOP;
            }
        } else
            clickFlag = CLIP_LINE_CLICK_NONE;

        return clickFlag;
    }

    public int getHeight() {    return mHeight; }
    public int getWidth()  {    return mWidth; }

    public int getLeft()    {   return mLeft + (int) mTranslateX; }
    public int getRight()   {   return mRight + (int) mTranslateX; }
    public int getTop()     {   return mTop + (int) mTranslateY; }
    public int getBottom()  {   return mBottom + (int) mTranslateY; }

    public float getTranslateX()    {   return mTranslateX; }
    public float getTranslateY()    {   return mTranslateY; }

    public float getScaleX()        {   return mScaleX; }
    public float getScaleY()        {   return mScaleY; }

    public int getLeftLn()      {   return mLeftLn; }
    public int getRightLn()     {   return mRightLn; }
    public int getBottomLn()    {   return mBottomLn; }
    public int getTopLn()       {   return mTopLn; }

    public void setViewHeight(int h)   { mViewHeight = h; }
    public void setDrawLineFlag(int f) { mClickDrawLineFlag = f; }

    public float transformMoveXCoordinateFromView(float x) { return (int)(x / mScaleX); }
    public float transformMoveYCoordinateFromView(float y) { return (int)(-y / mScaleY); }

    public void setLayout(int l, int r, int b, int t, int lnl, int lnr, int lnb, int lnt) {
        mLeft   = l;
        mRight  = r;
        mBottom = b;
        mTop    = t;

        mLeftLn   = lnl;
        mRightLn  = lnr;
        mBottomLn = lnb;
        mTopLn    = lnt;

        float texture[] = {
            0.00f, 0.00f,
            1.00f, 0.00f,

            1.00f, 0.25f,
            0.75f, 0.25f,
            0.25f, 0.25f,
            0.00f, 0.25f,

            0.00f, 0.75f,
            0.25f ,0.75f,
            0.75f ,0.75f,
            1.00f, 0.75f,

            1.00f, 1.00f,
            0.00f, 1.00f
        };

        byte indices[] = {
            0,1,2,
            0,2,5,

            3,2,9,
            3,9,8,

            5,4,7,
            5,7,6,

            6,9,10,
            6,10,11,
        };

        mIndiceslength = indices.length;

        ByteBuffer byteBuf = ByteBuffer.allocateDirect(texture.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mTextureBuffer = byteBuf.asFloatBuffer();
        mTextureBuffer.put(texture);
        mTextureBuffer.position(0);

        mIndexBuffer = ByteBuffer.allocateDirect(indices.length);
        mIndexBuffer.put(indices);
        mIndexBuffer.position(0);

//        float textureln[] = {
//            0.00f, 0.00f,
//            0.00f, 0.00f,
//            1.00f, 0.00f,
//            1.00f, 0.00f,
//
//            1.00f, 0.00f,
//            1.00f, 0.00f,
//            0.00f, 0.00f,
//            0.00f, 0.00f,
//
//            1.00f, 1.00f,
//            1.00f, 1.00f,
//            0.00f, 1.00f,
//            0.00f, 1.00f,
//
//            0.00f, 1.00f,
//            0.00f, 1.00f,
//            1.00f, 1.00f,
//            1.00f, 1.00f
//        };

//        float textureln[] = {
////              0.00f, 0.00f,
////              0.10f, 0.00f,
////              0.90f, 0.00f,
////              1.00f, 0.00f,
////
////              1.00f, 0.10f,
////              0.90f, 0.10f,
////              0.10f, 0.10f,
////              0.00f, 0.10f,
////
////              0.00f, 0.90f,
////              0.10f, 0.90f,
////              0.90f, 0.90f,
////              1.00f, 0.90f,
////
////              1.00f, 1.00f,
////              0.90f, 1.00f,
////              0.10f, 1.00f,
////              0.00f, 1.00f
//
//                0.50f, 0.50f,
//                0.50f, 0.50f,
//                0.50f, 0.50f,
//                0.50f, 0.50f,
//
//                0.50f, 0.50f,
//                1.00f, 0.00f,
//                0.00f, 0.00f,
//                0.00f, 0.00f,
//
//                0.00f, 1.00f,
//                0.00f, 1.00f,
//                1.00f, 1.00f,
//                0.50f, 0.50f,
//
//                0.50f, 0.50f,
//                1.00f, 1.00f,
//                0.00f, 1.00f,
//                0.00f, 1.00f
//            };
//
//        byte indicesln[] = {
//            0,1,6,      0,6,7,
//            1,2,5,      1,5,6,
//            2,3,4,      2,4,5,
//            5,4,11,     5,11,10,
//            7,6,9,      7,9,8,
//            8,9,14,     8,14,15,
//            9,10,13,    9,13,14,
//            10,11,12,   10,12,13
//        };
//
//        mIndiceslengthLn = indicesln.length;
//
//        byteBuf = ByteBuffer.allocateDirect(textureln.length * 4);
//        byteBuf.order(ByteOrder.nativeOrder());
//        mTextureBufferLn = byteBuf.asFloatBuffer();
//        mTextureBufferLn.put(textureln);
//        mTextureBufferLn.position(0);
//
//        mIndexBufferLn = ByteBuffer.allocateDirect(indicesln.length);
//        mIndexBufferLn.put(indicesln);
//        mIndexBufferLn.position(0);

        float texturelnleft[] = {
            0.00f, 0.00f,
            0.00f, 0.25f,
            1.00f, 0.25f,
            1.00f, 0.75f,
            0.00f, 0.75f,
            0.00f, 1.00f
        };

        byte indiceslnleft[] = {
            0,2,1,
            1,2,3,
            1,3,4,
            4,3,5
        };

        mIndiceslengthLnLeft = indiceslnleft.length;

        byteBuf = ByteBuffer.allocateDirect(texturelnleft.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mTextureBufferLnLeft = byteBuf.asFloatBuffer();
        mTextureBufferLnLeft.put(texturelnleft);
        mTextureBufferLnLeft.position(0);

        mIndexBufferLnLeft = ByteBuffer.allocateDirect(indiceslnleft.length);
        mIndexBufferLnLeft.put(indiceslnleft);
        mIndexBufferLnLeft.position(0);

        float texturelnbottom[] = {
            0.00f, 0.00f,
            0.25f, 0.00f,
            0.75f, 0.00f,
            1.00f, 0.00f,
            0.75f, 1.00f,
            0.25f, 1.00f
        };

        byte indiceslnbottom[] = {
            0,1,5,
            1,2,4,
            1,4,5,
            2,3,4
        };

        mIndiceslengthLnBottom = indiceslnbottom.length;

        byteBuf = ByteBuffer.allocateDirect(texturelnbottom.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mTextureBufferLnBottom = byteBuf.asFloatBuffer();
        mTextureBufferLnBottom.put(texturelnbottom);
        mTextureBufferLnBottom.position(0);

        mIndexBufferLnBottom = ByteBuffer.allocateDirect(indiceslnbottom.length);
        mIndexBufferLnBottom.put(indiceslnbottom);
        mIndexBufferLnBottom.position(0);

        float texturelnright[] = {
            1.00f, 0.00f,
            0.00f, 0.25f,
            1.00f, 0.25f,
            1.00f, 0.75f,
            0.00f, 0.75f,
            1.00f, 1.00f
        };

        byte indiceslnright[] = {
            0,2,1,
            1,2,3,
            1,3,4,
            4,3,5
        };

        mIndiceslengthLnRight = indiceslnright.length;

        byteBuf = ByteBuffer.allocateDirect(texturelnright.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mTextureBufferLnRight = byteBuf.asFloatBuffer();
        mTextureBufferLnRight.put(texturelnright);
        mTextureBufferLnRight.position(0);

        mIndexBufferLnRight = ByteBuffer.allocateDirect(indiceslnright.length);
        mIndexBufferLnRight.put(indiceslnright);
        mIndexBufferLnRight.position(0);

        float texturelntop[] = {
            0.00f, 0.00f,
            0.75f, 0.00f,
            1.00f, 1.00f,
            0.75f, 1.00f,
            0.25f, 1.00f,
            0.00f, 1.00f
        };

        byte indiceslntop[] = {
            0,4,5,
            0,1,3,
            0,3,4,
            1,2,3
        };

        mIndiceslengthLnTop = indiceslntop.length;

        byteBuf = ByteBuffer.allocateDirect(texturelntop.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mTextureBufferLnTop = byteBuf.asFloatBuffer();
        mTextureBufferLnTop.put(texturelntop);
        mTextureBufferLnTop.position(0);

        mIndexBufferLnTop = ByteBuffer.allocateDirect(indiceslntop.length);
        mIndexBufferLnTop.put(indiceslntop);
        mIndexBufferLnTop.position(0);
    }

    public void changeLineVertices(int l, int r, int b, int t) {
        mLeftLn   = l;
        mRightLn  = r;
        mBottomLn = b;
        mTopLn    = t;

        refreshVertices();
    }

    public void loadTexture(GL10 gl) {
        Bitmap.Config config = Bitmap.Config.ARGB_8888;
        Bitmap bitmap = Bitmap.createBitmap(1, 1, config);
        Canvas canvas = new Canvas(bitmap);
        bitmap.eraseColor(0);
        canvas.drawColor(mColor);

        gl.glGenTextures(2, mTextures, 0);

        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[0]);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

        bitmap.eraseColor(0);
        canvas.drawColor(mColorLn);

        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[1]);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

//        Bitmap bitmap2 = Bitmap.createBitmap(4, 4, config);
//        bitmap2.eraseColor(0);
//        Canvas canvas2 = new Canvas(bitmap2);
//        canvas2.drawColor(mColorLn);
//        Paint p = new Paint();
//        p.setColor(mColorLnAct);
//        canvas2.drawRect(1f, 1f, 3f, 3f, p);

        bitmap.eraseColor(0);
        canvas.drawColor(mColorLnAct);

        gl.glBindTexture(GL10.GL_TEXTURE_2D, mTextures[2]);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);

        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
        gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);

        GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);

        bitmap.recycle();
    }

    /* Private Function */
    public void refreshVertices() {
        int leftLnIn   = mLeftLn   - mWidthLnCur;
        int rightLnIn  = mRightLn  + mWidthLnCur;
        int bottomLnIn = mBottomLn - mWidthLnCur;
        int topLnIn    = mTopLn    + mWidthLnCur;

        float vertices[] = {
            (float) mLeft , (float) mBottom, // 0
            (float) mRight, (float) mBottom, // 1

            (float) mRight,     (float) bottomLnIn, // 2
            (float) rightLnIn,  (float) bottomLnIn, // 3
            (float) leftLnIn,   (float) bottomLnIn, // 4
            (float) mLeft,      (float) bottomLnIn, // 5

            (float) mLeft,      (float) topLnIn, // 6
            (float) leftLnIn,   (float) topLnIn, // 7
            (float) rightLnIn,  (float) topLnIn, // 8
            (float) mRight,     (float) topLnIn, // 9

            (float) mRight, (float) mTop, // 10
            (float) mLeft,  (float) mTop // 11
        };

//        float verticesIn[] = {
//            (float) leftLnIn,   (float) bottomLnIn, // 0
//            (float) rightLnIn,  (float) bottomLnIn, // 1
//
//            (float) rightLnIn,  (float) mBottomLn, // 2
//            (float) mRightLn,   (float) mBottomLn, // 3
//            (float) mLeftLn,    (float) mBottomLn, // 4
//            (float) leftLnIn,   (float) mBottomLn, // 5
//
//            (float) leftLnIn,   (float) mTopLn, // 6
//            (float) mLeftLn,    (float) mTopLn, // 7
//            (float) mRightLn,   (float) mTopLn, // 8
//            (float) rightLnIn,  (float) mTopLn, // 9
//
//            (float) rightLnIn,  (float) topLnIn, // 10
//            (float) leftLnIn,   (float) topLnIn  // 11
//        };

        float verticesInLeft[] = {
            (float) leftLnIn,   (float) bottomLnIn,
            (float) leftLnIn,   (float) mBottomLn,
            (float) mLeftLn,    (float) mBottomLn,
            (float) mLeftLn,    (float) mTopLn,
            (float) leftLnIn,   (float) mTopLn,
            (float) leftLnIn,   (float) topLnIn
        };

        float verticesInRight[] = {
            (float) rightLnIn,  (float) bottomLnIn,
            (float) mRightLn,   (float) mBottomLn,
            (float) rightLnIn,  (float) mBottomLn,
            (float) rightLnIn,  (float) mTopLn,
            (float) mRightLn,   (float) mTopLn,
            (float) rightLnIn,  (float) topLnIn
        };

        float verticesInBottom[] = {
            (float) leftLnIn,   (float) bottomLnIn,
            (float) mLeftLn,    (float) bottomLnIn,
            (float) mRightLn,   (float) bottomLnIn,
            (float) rightLnIn,  (float) bottomLnIn,
            (float) mRightLn,   (float) mBottomLn,
            (float) mLeftLn,    (float) mBottomLn
        };

        float verticesInTop[] = {
            (float) mLeftLn,    (float) mTopLn,
            (float) mRightLn,   (float) mTopLn,
            (float) rightLnIn,  (float) topLnIn,
            (float) mRightLn,   (float) topLnIn,
            (float) mLeftLn,    (float) topLnIn,
            (float) leftLnIn,   (float) topLnIn
        };

        ByteBuffer byteBuf = ByteBuffer.allocateDirect(vertices.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mVertexBuffer = byteBuf.asFloatBuffer();
        mVertexBuffer.put(vertices);
        mVertexBuffer.position(0);

//        float verticesln[] = {
//            (float) leftLnIn , (float) bottomLnIn, // 0
//            (float) mLeftLn,   (float) bottomLnIn, // 1
//            (float) mRightLn , (float) bottomLnIn, // 2
//            (float) rightLnIn, (float) bottomLnIn, // 3
//
//            (float) rightLnIn, (float) mBottomLn,  // 4
//            (float) mRightLn,  (float) mBottomLn,  // 5
//            (float) mLeftLn,   (float) mBottomLn,  // 6
//            (float) leftLnIn,  (float) mBottomLn,  // 7
//
//            (float) leftLnIn,  (float) mTopLn,     // 8
//            (float) mLeftLn,   (float) mTopLn,     // 9
//            (float) mRightLn,  (float) mTopLn,     // 10
//            (float) rightLnIn, (float) mTopLn,     // 11
//
//            (float) rightLnIn, (float) topLnIn,    // 12
//            (float) mRightLn,  (float) topLnIn,    // 13
//            (float) mLeftLn,   (float) topLnIn,    // 14
//            (float) leftLnIn,  (float) topLnIn     // 15
//        };
//
//        byteBuf = ByteBuffer.allocateDirect(verticesln.length * 4);
//        byteBuf.order(ByteOrder.nativeOrder());
//        mVertexBufferLn = byteBuf.asFloatBuffer();
//        mVertexBufferLn.put(verticesln);
//        mVertexBufferLn.position(0);

        byteBuf = ByteBuffer.allocateDirect(verticesInLeft.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mVertexBufferLnLeft = byteBuf.asFloatBuffer();
        mVertexBufferLnLeft.put(verticesInLeft);
        mVertexBufferLnLeft.position(0);

        byteBuf = ByteBuffer.allocateDirect(verticesInRight.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mVertexBufferLnRight = byteBuf.asFloatBuffer();
        mVertexBufferLnRight.put(verticesInRight);
        mVertexBufferLnRight.position(0);

        byteBuf = ByteBuffer.allocateDirect(verticesInBottom.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mVertexBufferLnBottom = byteBuf.asFloatBuffer();
        mVertexBufferLnBottom.put(verticesInBottom);
        mVertexBufferLnBottom.position(0);

        byteBuf = ByteBuffer.allocateDirect(verticesInTop.length * 4);
        byteBuf.order(ByteOrder.nativeOrder());
        mVertexBufferLnTop = byteBuf.asFloatBuffer();
        mVertexBufferLnTop.put(verticesInTop);
        mVertexBufferLnTop.position(0);
    }
}
